package com.ruoyi.aitapp.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.aitapp.vo.APPFormVO;
import com.ruoyi.aitapp.vo.APPViewVO;
import com.ruoyi.aitcommon.config.ConfigManager;
import com.ruoyi.aitcommon.utils.*;
import com.ruoyi.aitcommon.vo.PageDataVO;
import com.ruoyi.aitcommon.vo.PageInfoVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

@Component
public class APPFormUtils {
    @Autowired
    ConfigManager configManager;
    @Autowired
    APPConfigUtils appConfigUtils;
    @Autowired
    APPDataUtils appDataUtils;
    @Autowired
    U9RestUtils u9RestUtils;

    /**
     * 获取参数中的分页信息
     * @param params 传入参数
     * @return 分页信息
     */
    private PageInfoVO getParamsPageInfo(Map<String,Object> params) throws Exception {
        if(ObjUtils.isBlank(params)) return new PageInfoVO();
        final PageInfoVO pageInfoVO = JSONObject.toJavaObject(new JSONObject(params), PageInfoVO.class);
        //依据参数设置默认分页大小
        final int pageSize = appConfigUtils.getAPPParamsInt("pageSize");
        if(pageSize>0)
            pageInfoVO.setPageSize(pageSize);
        return pageInfoVO;
    }

    /**
     * 依据传入参数,设置 FORM VIEW 数据
     * @param pageCode 页面代码
     * @param inParams 传入Params
     * @param appFormVO FORMVO对象
     */
    public APPFormVO setFormViewData(String pageCode,Object inParams, APPFormVO appFormVO) throws Exception {
//        页面参数合并
        setFormParams(inParams, appFormVO);
        final LinkedHashMap<String, Object> params = appFormVO.getParams();
        ExceptionUtils.checkBlankOrUndefined(params.get("operation"),"页面代码[{}],params配置中的operation为空",pageCode);
        final String oper = params.get("operation").toString();
        ExceptionUtils.checkBlankOrUndefined(params.get("view"),"页面代码[{}],params配置中的view为空",pageCode);
        final String viewName = (String)params.get("view");
        final PageInfoVO pageInfoVO = this.getParamsPageInfo(params);
        final APPViewVO viewVO = appFormVO.getViews().get(viewName);
        ExceptionUtils.checkBlankOrUndefined(viewVO,"页面代码[{}],页面配置中未找到view:[{}]",pageCode,viewName);

        if(oper.equals("query")){
//            查询页面数据,依据查询条件获取数据
//            获取查询条件构造的PATH
            String path= getViewQueryPath(appFormVO,viewName);
            String order= viewVO.getDataDefOrder();
            final PageDataVO retData = appDataUtils.queryERPByParam(viewVO.getDataView(), path,order, pageInfoVO);
            viewVO.setData(retData);
            setViewQueryPathsData(appFormVO,viewName);
        }else if(oper.equals("transfer")){
            //转单处理
            //设置采集数据
            final JSONArray fromData = getFromData(pageCode, appFormVO);
            setCollectData(pageCode, appFormVO, fromData);
        } else if (oper.equals("add")) {
            //新增
            JSONArray fromData =new JSONArray();
            fromData.add(new JSONObject());
            //设置采集数据
            setCollectData(pageCode, appFormVO, fromData);
        }
        else if(oper.equals("approve")){
            //审批详情
            final LinkedHashMap<String, APPViewVO> views = appFormVO.getViews();
            for(String key:views.keySet()){
                //获取所有视图数据
                final APPViewVO curViewVO = views.get(key);
                //依据默认查询条件获取数据
                final String defPath = curViewVO.getDataDefPath();
                final JSONArray fromData = getFromData(pageCode, appFormVO);
                final Object defPath1 = JSONParamUtils.transParamsJSONValue(defPath, fromData.getJSONObject(0), false);
                //查询数据
                final PageDataVO retData = appDataUtils.queryERPByParam(curViewVO.getDataView()
                        , defPath1.toString(),curViewVO.getDataDefOrder(), pageInfoVO);
                if(curViewVO.getType().equals("form")){
                    //表单数据需要合并fromData
                    for(Map<String,Object> row: retData.getRows()){
                        row.putAll(fromData.getJSONObject(0));
                    }
                }
                curViewVO.setData(retData);
            }
        }
        else{
            ExceptionUtils.throwException(null,"页面代码[{}],不支持的操作:[%s]",pageCode,oper);
        }
        return appFormVO;
    }

    /**
     * 获取Form.params对象中的fromData数据
     * @param pageCode
     * @param appFormVO
     * @return
     */
    private static JSONArray getFromData(String pageCode, APPFormVO appFormVO) throws Exception {
        final Object fromDataObj = appFormVO.getParams().get("fromData");
        ExceptionUtils.checkBlankOrUndefined(fromDataObj,"页面代码[{}],fromData为空", pageCode);
        final JSONArray fromData = (JSONArray) fromDataObj;
        return fromData;
    }

    /**
     * 构造查询条件Path对应的默认值Data
     * @param appFormVO
     * @param viewName
     * @return
     */
    private void setViewQueryPathsData(APPFormVO appFormVO, String viewName) {

        final LinkedHashMap<String, Object> params = appFormVO.getParams();
        if(ObjUtils.isBlank(params)) return;
        final APPViewVO viewVO = appFormVO.getViews().get(viewName);
        if(ObjUtils.isBlank(viewVO)) return;
        final Map<String, Map<String, Object>> paths = viewVO.getPaths();
        if(ObjUtils.isBlank(paths)) return;

        LinkedHashMap<String, Object> pathsData = new LinkedHashMap<>();
        for(String key:paths.keySet()){
            //循环View定义的path分组
            final Map<String, Object> pathGroup = paths.get(key);
            final Object fieldsObj = pathGroup.get("fields");
            if(ObjUtils.isBlank(fieldsObj)) continue;
            final Map<String, Object> fieldsMap = (Map<String, Object>) fieldsObj;
            for(String key1:fieldsMap.keySet()){
                //循环path分组的每个字段
                if(params.containsKey(key1)&&ObjUtils.isNotBlank(params.get(key1))){
                    //form.params参数中包含该查询字段,并且有值
                    pathsData.put(key1, params.get(key1));
                }
            }
        }
        viewVO.setPathsData(pathsData);
    }

    /**
     * 获取跳转后页面参数Params
     * 要求fromData中包含跳转参数
     * 通过 redirectMap 获取跳转后页面编码
     * @param pageCode 跳转页面编码
     * @param appFormVO 跳转页面Form
     */
    private LinkedHashMap<String, Object> getRedirectParam(String pageCode, APPFormVO appFormVO) throws Exception {
        //获取跳转Map
        final LinkedHashMap<String, Object> params = appFormVO.getParams();
        final Map<String,Object> redirectMap = (Map<String, Object>)params.get("redirectMap");
        //获取跳转数据
        final List<Map<String,Object>> fromData=(List<Map<String, Object>>) params.get("fromData");
        Map<String,Object> data=null;
        if(ObjUtils.isNotBlank(fromData)){
            data=(Map<String, Object>) fromData.get(0);
        }else{
            data=params;
        }
        //从数据中获取跳转pageCode
        final String redirectField = (String) params.get("redirectField");
        final String redirectKey = (String) data.get(redirectField);
        final String toPageCode = (String) redirectMap.get(redirectKey);//跳转目标页面
        ExceptionUtils.checkBlankOrUndefined(toPageCode,"页面代码[{}],跳转目标[{}]对应页面为空",pageCode,redirectKey);
        //构造toParams
        final LinkedHashMap<String, Object> toParams = appFormVO.getToParams();
        toParams.put("toPageCode",toPageCode);
        //将fromData数据设置到toParams
        toParams.put("fromData",fromData);
        return toParams;
    }

    /**
     * 设置转单数据到采集
     * @param pageCode 页面代码
     * @param appFormVO FORMVO对象
     * @param fromData 转单数据
     */
    private static void setCollectData(String pageCode, APPFormVO appFormVO, JSONArray fromData) throws Exception {
        //获取collect类型view
        APPViewVO collectVO=null;
        for(APPViewVO view: appFormVO.getViews().values()){
            if(view.getType().equals("collect")){
                collectVO=view;
            }
        }
        ExceptionUtils.checkBlankOrUndefined(collectVO,"页面代码[{}],未找到collect类型view", pageCode);
        //fromData,设置Default值
        //未设置Default属性或Default=""的属性,默认=""
        //设置Default值的属性,从form.params中获取翻译后的值
        ExceptionUtils.checkBlankOrUndefined(fromData,"页面代码[{}],fromData为空", pageCode);
        JSONObject collectData = fromData.getJSONObject(0);
        for(String key:collectVO.getFields().keySet()){
            //跳过已存在的值
            if(collectData.containsKey(key)
                    && ObjUtils.isNotBlank(collectData.get(key)))
                continue;
            //循环字段定义
            final Map<String, Object> field = collectVO.getFields().get(key);
            if(ObjUtils.isBlank(field.get("default"))){
                //默认值不存在,默认=""
                collectData.put(key,"");
            }else{
                //如果存在default值,则设置到fromData中
                final Object defaultValue = field.get("default");
                final Object transValue = JSONParamUtils.transParamsJSONValue(defaultValue.toString(),
                        appFormVO.getParams(), false);
                collectData.put(key,transValue);
            }
        }
        //设置数据到collect视图
        PageDataVO retData = new PageDataVO();
        retData.setRows(fromData);
        collectVO.setData(retData);
    }

    /**
     * 设置APPFormVO中的参数Params
     * @param inParams
     * @param appFormVO
     * @return
     */
    private void setFormParams(Object inParams, APPFormVO appFormVO) throws Exception {
        Map<String, Object> params = appFormVO.getParams();
        //翻译JSON配置中的params
        params=(Map<String, Object>) JSONParamUtils.transParamsJSON(params,configManager.getContext());
        if(ObjUtils.isNotBlank(inParams)) {
//        传入参数覆盖配置参数
            Map<String, Object> map = (Map<String, Object>) inParams;
            //这里参数覆盖策略:
            //要判断有值才覆盖,确保配置参数有效
            //修改策略,直接覆盖,传入参数优先
            for (String key : map.keySet()) {
                params.put(key, map.get(key));
//                if (ObjUtils.isNotBlank(map.get(key))) {
//                    params.put(key, map.get(key));
//                }
            }
        }
        LinkedHashMap map1=new LinkedHashMap();
        map1.putAll(params);
        appFormVO.setParams(map1);
    }

    /**
     * 依据View中的查询path对象,构造where语句
     * @param appFormVO
     * @param viewName 视图名称
     * @return 构造出的Path字符串
     */
    private static String getViewQueryPath(APPFormVO appFormVO,String viewName) throws Exception {
        String path = "";
        final LinkedHashMap<String, Object> params = appFormVO.getParams();
        if(ObjUtils.isBlank(params)) return path;
        final APPViewVO appViewVO = appFormVO.getViews().get(viewName);
        if(ObjUtils.isBlank(appViewVO)) return path;
        final Map<String, Map<String, Object>> paths = appViewVO.getPaths();
        if(ObjUtils.isBlank(paths)) return path;

        //获取预定义path
        final String defPath = appViewVO.getDataDefPath();
        final Object defPath1 = JSONParamUtils.transParamsJSONValue(defPath, params, false);
        //获取查询path
        for(String groupKey:paths.keySet()){
            //循环View定义的path分组
            final Map<String, Object> pathGroup = paths.get(groupKey);
            final Object fieldsObj = pathGroup.get("fields");
            if(ObjUtils.isBlank(fieldsObj)) continue;
            final Map<String, Object> fieldsMap = (Map<String, Object>) fieldsObj;
            for(String fieldKey:fieldsMap.keySet()){
                //循环path分组的每个字段
                final Map<String,Object> fieldMap = (Map<String,Object>)fieldsMap.get(fieldKey);
                Object defaultVal = fieldMap.get("default");
                if(ObjUtils.isNotBlank(defaultVal)&&params.get(fieldKey)==null){
                    //defaultVal非空,params中未包含,将defaultVal添加到params中
                    params.put(fieldKey,defaultVal);
                }
                if(params.containsKey(fieldKey)&&ObjUtils.isNotBlank(params.get(fieldKey))){
                    //form.params参数中包含该查询字段,并且有值
                    Object fieldPath = fieldMap.get("path");
                    if(ObjUtils.isNotBlank(fieldPath)){
                        //翻译path,从params中获取查询值
                        fieldPath = JSONParamUtils.transParamsJSONValue(fieldPath.toString(), params, false);
                        if(ObjUtils.isNotBlank(fieldPath)){
                            //path拼接
                            path += " and "+fieldPath;
                        }
                    }
                }
            }
        }
        //返回查询path+定义path
        if(ObjUtils.isNotBlank(defPath1)){
            path=path+" and "+defPath1;
        }
        return path;
    }

    /**
     * 依据页面code获取APPFormVO
     * 如果页面配置为redirect,则获取跳转后的页面APPFormVO
     * @param pageCode 页面编码
     * @param inParams 页面参数
     * @return
     */
    public APPFormVO getAppFormVO(String pageCode,Object inParams) throws Exception {
//        依据pageCode,获取APPFormVO
        final Map<String, Object> pageMap = appConfigUtils.getPage(pageCode);
        ExceptionUtils.checkBlankOrUndefined(pageMap.get("form"),"page对象form为空");
        Object formObj = configManager.getContextByParm(pageMap.get("form").toString(),false);
        APPFormVO appFormVO = JSONObject.toJavaObject((JSON) formObj, APPFormVO.class);
//        页面参数合并
        setFormParams(inParams, appFormVO);
//        跳转页面处理
        if(ObjUtils.isNotBlank(appFormVO.getParams())){
            final Object oper = appFormVO.getParams().get("operation");
            if(oper!=null&&oper.equals("redirect")) {
                //跳转页面处理
                LinkedHashMap<String, Object> toParams = getRedirectParam(pageCode, appFormVO);
                final String toPageCode = toParams.get("toPageCode").toString();
                //递归调用,获取跳转后页面FormVO
                appFormVO = getAppFormVO(toPageCode,toParams);
            }
        }
        return appFormVO;
    }

    /**
     * 单据数据保存至U9
     * @param formVO
     * @param datas 传入数据集合
     * @return 数据对象,类型为JSONObject或JSONArray
     */
    public Object saveFormData(APPFormVO formVO, JSONArray datas) throws Exception {
        //读取配置信息
        ExceptionUtils.checkBlankOrUndefined(datas,"datas 为空");
        //获取save配置json
        JSONObject saveJson = (JSONObject)configManager.getContextByParm(formVO.getSaveTrans(),false);
        //调用U9单据接口
        Object ret = null;
        final JSONObject restParam = appConfigUtils.getAPPParamsJson("erprest");
        if(restParam.getString("type").equals("U9")){
            ret = U9Call(datas,saveJson);
            //调用U9条码使用接口
            barCodeCall(datas,saveJson,ret);
        }
        return ret;
    }

    /**
     * 单据数据保存至U9
     * @param datas 传入数据集合
     * @param saveJson 保存配置
     * @return 数据对象,类型为JSONObject或JSONArray
     */
    private Object U9Call(JSONArray datas, JSONObject saveJson) throws Exception {
        Object ret;
        JSONObject erpRest=saveJson.getJSONObject("ERPRest");
        ExceptionUtils.checkBlankOrUndefined(erpRest,"ERPRest 为空");
        //构造单头数据
        final Map<String, Object> context = MapUtils.combineMap(configManager.getContext(), datas.getJSONObject(0));
        final JSONObject docFields = saveJson.getJSONObject("docFields");
        final Object dataDoc = JSONParamUtils.transParamsJSON(docFields, new JSONObject(context));
        //构造单行数据
        List<Object> dataLines = new ArrayList<>();
        final String lineField = erpRest.getString("lineField");
        if(ObjUtils.isNotBlank(lineField)){
            final JSONObject lineFields = saveJson.getJSONObject("lineFields");
            for (Object data: datas) {
                //构造单行数据
                final Object dataLine = JSONParamUtils.transParamsJSON(lineFields, (JSONObject)data);
                //构造子行数据
                final String subLineField = erpRest.getString("subLineField");
                if(ObjUtils.isNotBlank(subLineField)){
                    //构造子行数据
                    final JSONObject subLineFields = saveJson.getJSONObject("subLineFields");
                    final Object dataSubLine = JSONParamUtils.transParamsJSON(subLineFields, (JSONObject)data);
                    Map<String,Object> dataline1=(Map<String, Object>) dataLine;
                    dataline1.put(subLineField,Arrays.asList(dataSubLine));
                }
                dataLines.add(dataLine);
            }
        }
        //构造U9接口数据
        JSONObject u9data=new JSONObject();
        u9data.putAll((JSONObject)dataDoc);//单头数据
        if(ObjUtils.isNotBlank(lineField)){
            u9data.put(erpRest.getString("lineField"),dataLines);
        }
        //调用U9接口,如果失败会直接抛异常
        ret = u9RestUtils.callU9Rest(datas.getJSONObject(0),erpRest.getString("url"),Arrays.asList(u9data));
        return ret;
    }

    /**
     * 条码使用接口调用
     * @param datas 数据集合
     * @param saveJson 保存配置
     * @param u9ret U9返回结果
     */
    private Object barCodeCall(JSONArray datas, JSONObject saveJson , Object u9ret) throws Exception {
        JSONObject erpRest=saveJson.getJSONObject("ERPRest");
        final String barcodeField = erpRest.getString("barcodeField");
        final JSONObject barcodeUseFields = saveJson.getJSONObject("barcodeUseFields");
        List<Object> barDatas = new ArrayList<>();
        Object ret = null;
        if(ObjUtils.isNotBlank(barcodeField)&&ObjUtils.isNotBlank(barcodeUseFields)){
            //更新条码使用档的条件:barcodeField,barcodeUseFields非空
            //合并传入data和调用U9接口的返回值,作为context翻译barcodeUseFields配置
            for (Object data: datas) {
                Map<String,Object> barData=(Map<String, Object>) data;
                JSONObject retjson=JSONUtils.getJSONObjectByObject(u9ret);
                barData.putAll(retjson);
                final Object barData1 = JSONParamUtils.transParamsJSON(barcodeUseFields, barData);
                barDatas.add(barData1);
            }
            //调用U9接口,生成条码使用档
            ret = u9RestUtils.callU9Rest(datas.getJSONObject(0),erpRest.getString("barUrl"),barDatas);
        }
        return ret;
    }
}
